package top.system.dept.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import top.system.dept.mapper.InvoiceItemMapper;
import top.system.dept.mapper.InvoiceMapper;
import top.system.dept.pojo.Invoice;
import top.system.dept.pojo.InvoiceItem;
import top.system.dept.pojo.SysResp;
import top.system.dept.pojo.User;
import top.system.dept.utils.RespUtil;
import top.system.dept.utils.StringUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class InvoiceService {

    @Autowired
    UserService userService;

    @Autowired
    InvoiceMapper invoiceMapper;

    @Autowired
    InvoiceItemMapper invoiceItemMapper;

    @Value("${invoice.save.path}")
    private String invoiceSavePath;

    @Value("${invoice.save.file.prefix}")
    private String invoiceFilePrefix;

    @Transactional(rollbackFor = {Exception.class})
    public SysResp uploadInvoice(MultipartFile[] invoiceFiles,
                                 String userModal,
                                 Invoice invoice,
                                 InvoiceItem[] invoiceItems,
                                 MultipartHttpServletRequest req) {

        if (!checkInvoice(invoiceFiles, invoice, invoiceItems)) {
            return RespUtil.illegalParam();
        }

        User user = checkUser(userModal);
        if (user == null) {
            return RespUtil.noLogin();
        }

        String[] saveFileNames;

        try {
            saveFileNames = saveFiles(invoiceFiles, req);
            // 执行成功
        } catch (IOException e) {
            return RespUtil.fail();
        }

        wrapToURL(saveFileNames, req);

        // 封装为数据库对象
        invoice.setFilePaths(StringUtil.arrayToString(saveFileNames));
//        invoice.setItems(invoiceItems);

        invoice.setApplyUser(user);
        invoice.setDept(user.getDept());
        invoice.setApplyDate(new Date());

        // 保存到数据库
        invoiceMapper.addInvoice(invoice);

        invoiceItemMapper.addInvoiceItem(Arrays.asList(invoiceItems));

        return RespUtil.success();
    }

    private User checkUser(String userModal) {
        User user = userService.getUserByModal(userModal);
        return user;
    }

    // 返回所有文件的文件名
    public String[] saveFiles(MultipartFile[] files, MultipartHttpServletRequest request) throws IOException {

        if (files == null) {
            return new String[0];
        }

        String[] fileNames = new String[files.length];

        String savePath = request.getServletContext().getRealPath("") + invoiceSavePath;

        // 保存文件夹
        File saveDirectory = new File(savePath);
        // 不存在则创建
        if ((!saveDirectory.isDirectory()) || (!saveDirectory.exists())) {
            saveDirectory.mkdirs();
        }

        int i = 0;
        for (MultipartFile file : files) {


            // 生成文件名，以时间戳为文件名，不考虑文件名重复覆盖
            String fileName = invoiceFilePrefix + System.currentTimeMillis();

            // 获取扩展名
            String suffix = getOriginalFileSuffix(file);

            String destFilePath = savePath + File.separator + fileName + suffix;
            // 最终文件路径
            File destFile = new File(destFilePath);
            file.transferTo(destFile);
            fileNames[i] = fileName + suffix;
            i++;
        }

        return fileNames;
    }

    private String getOriginalFileSuffix(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        return originalFilename.substring(originalFilename.indexOf("."));
    }

    private void wrapToURL(String[] fileNames, HttpServletRequest req) {
        String scheme = req.getScheme();
        String serverName = req.getServerName();
        String contextPath = req.getContextPath();
        String baseUrl = scheme + "://" + serverName + contextPath + invoiceSavePath;
        for (int i = 0; i < fileNames.length; i++) {
            fileNames[i] = baseUrl + fileNames[i];
        }
    }

    private boolean checkInvoice(MultipartFile[] files, Invoice invoice, InvoiceItem[] items) {
        if (files == null || invoice == null || items == null) {
            return false;
        }
        if (files.length == 0 || items.length == 0) {
            return false;
        }
        if (!StringUtils.hasText(invoice.getInvoiceId())) {
            return false;
        }

        if (!StringUtils.hasText(invoice.getAccountBank())) {
            return false;
        }

        if (invoice.getAmount() == null) {
            return false;
        }

        if (invoice.getDate() == null) {
            return false;
        }

        if (invoice.getDate().after(new Date())) {
            return false;
        }
        return true;
    }

    public SysResp getInvoicesByModal(String userModal) {
        User user = userService.getUserByModal(userModal);
        if (user == null) {
            return RespUtil.noLogin();
        }

        List<Invoice> invoices = invoiceMapper.getInvoiceByUser(user.getId());
        for (Invoice invoice : invoices) {
            invoice.setFilePathArr(StringUtil.stringToArray(invoice.getFilePaths()));
        }
        return RespUtil.successData("invoices", invoices);

    }

    public SysResp getInvoiceByDate(String userModal, long begin, long end) {
        if (!userService.canUseRoot(userModal)) {
            return RespUtil.fail();
        }
        Date beginDate = new Date(begin);
        Date endDate = new Date(end);
        List<Invoice> invoices = invoiceMapper.getInvoiceByDate(beginDate, endDate);
        for (Invoice invoice : invoices) {
            invoice.setFilePathArr(StringUtil.stringToArray(invoice.getFilePaths()));
        }
        return RespUtil.successData("invoices", invoices);
    }


}
